package com.gitee.wsl.coroutines.job

import com.gitee.wsl.coroutines.job.sheduler.IScheduler
import com.gitee.wsl.time.calendar.Calendar
import com.gitee.wsl.coroutines.job.trigger.ITrigger
import com.gitee.wsl.coroutines.job.trigger.TriggerKey
import kotlin.time.ExperimentalTime
import kotlin.time.Instant

@OptIn(ExperimentalTime::class)
interface IJobExecutionContext {
    /**
     *
     *
     * Get a handle to the `Scheduler` instance that fired the
     * `Job`.
     *
     */
    val scheduler: IScheduler

    /**
     *
     *
     * Get a handle to the `Trigger` instance that fired the
     * `Job`.
     *
     */
    val trigger: ITrigger?

    /**
     *
     *
     * Get a handle to the `Calendar` referenced by the
     * `Trigger` instance that fired the `Job`.
     *
     */
    val calendar: Calendar?

    /**
     *
     *
     * If the `Job` is being re-executed because of a 'recovery'
     * situation, this method will return `true`.
     *
     */
    val isRecovering: Boolean

    /**
     * Return the `TriggerKey` of the originally scheduled and now
     * recovering job.
     *
     *
     * When recovering a previously failed job execution this method returns the
     * identity of the originally firing trigger. This recovering job will have
     * been scheduled for the same firing time as the original job, and so is
     * available via the [.getScheduledFireTime] method. The original
     * firing time of the job can be accessed via the
     * [IScheduler.FAILED_JOB_ORIGINAL_TRIGGER_FIRETIME_IN_MILLISECONDS]
     * element of this job's `JobDataMap`.
     *
     * @return the recovering trigger details
     * @throws IllegalStateException
     * if this is not a recovering job.
     */
    val recoveringTriggerKey: TriggerKey?

    val refireCount: Int

    /**
     *
     *
     * Get the convenience `JobDataMap` of this execution context.
     *
     *
     *
     * The `JobDataMap` found on this object serves as a convenience -
     * it is a merge of the `JobDataMap` found on the
     * `JobDetail` and the one found on the `Trigger`, with
     * the value in the latter overriding any same-named values in the former.
     * *It is thus considered a 'best practice' that the execute code of a Job
     * retrieve data from the JobDataMap found on this object.*
     *
     *
     *
     * NOTE: Do not expect value 'set' into this JobDataMap to somehow be set or
     * persisted back onto a job's own JobDataMap - even if it has the
     * `@PersistJobDataAfterExecution` annotation.
     *
     *
     *
     * Attempts to change the contents of this map typically result in an
     * `IllegalStateException`.
     *
     */
    val mergedJobDataMap: JobDataMap

    /**
     *
     *
     * Get the `JobDetail` associated with the `Job`.
     *
     */
    val jobDetail: JobDetail

    /**
     *
     *
     * Get the instance of the `Job` that was created for this
     * execution.
     *
     *
     *
     * Note: The Job instance is not available through remote scheduler
     * interfaces.
     *
     */
    val jobInstance: IJob?

    /**
     * The actual time the trigger fired. For instance the scheduled time may have
     * been 10:00:00 but the actual fire time may have been 10:00:03 if the
     * scheduler was too busy.
     *
     * @return Returns the fireTime.
     * @see .getScheduledFireTime
     */
    val fireTime: Instant?

    /**
     * The scheduled time the trigger fired for. For instance the scheduled time
     * may have been 10:00:00 but the actual fire time may have been 10:00:03 if
     * the scheduler was too busy.
     *
     * @return Returns the scheduledFireTime.
     * @see .getFireTime
     */
    val scheduledFireTime: Instant?

    val previousFireTime: Instant?

    val nextFireTime: Instant?

    /**
     * Get the unique Id that identifies this particular firing instance of the
     * trigger that triggered this job execution. It is unique to this
     * JobExecutionContext instance as well.
     *
     * @return the unique fire instance id
     * @see IScheduler.interrupt
     */
    val fireInstanceId: String?

    /**
     * Returns the result (if any) that the `Job` set before its
     * execution completed (the type of object set as the result is entirely up to
     * the particular job).
     *
     *
     * The result itself is meaningless to Quartz, but may be informative to
     * `[IJobListener]s` or
     * `[ITriggerListener]s` that are watching the job's
     * execution.
     *
     *
     * @return Returns the result.
     */
    /**
     * Set the result (if any) of the `Job`'s execution (the type of
     * object set as the result is entirely up to the particular job).
     *
     *
     * The result itself is meaningless to Quartz, but may be informative to
     * `[IJobListener]s` or
     * `[ITriggerListener]s` that are watching the job's
     * execution.
     *
     */
    var result: Any?

    /**
     * The amount of time the job ran for (in milliseconds). The returned value
     * will be -1 until the job has actually completed (or thrown an exception),
     * and is therefore generally only useful to `JobListener`s and
     * `TriggerListener`s.
     *
     * @return Returns the jobRunTime.
     */
    val jobRunTime: Long

    /**
     * Put the specified value into the context's data map with the given key.
     * Possibly useful for sharing data between listeners and jobs.
     *
     *
     * NOTE: this data is volatile - it is lost after the job execution completes,
     * and all TriggerListeners and JobListeners have been notified.
     *
     *
     * @param key
     * the key for the associated value
     * @param value
     * the value to store
     */
    fun put(key: Any, value: Any?)

    /**
     * Get the value with the given key from the context's data map.
     *
     * @param key
     * the key for the desired value
     */
    fun get(key: Any): Any?
}
